package com.example.mq.mqserver.core;

import lombok.Data;

import java.io.Serializable;
import java.util.UUID;

/**
 * 表示一个要传递的消息
 * 此处的 Message 对象是要在网络传输的，并且也要写到文件中
 * 此时就需要 针对 Message 进行序列化和反序列化
 * 此处用标准库自带的 序列化/反序列化操作
 */
@Data
public class Message implements Serializable {

    // 这两个属性是 Message 最核心的部分
    private BasicProperties basicProperties = new BasicProperties();
    private byte[] body;

    // 下面的属性则是辅助用的属性
    // Message 后续会存储到文件中（如果持久化的话）
    // 一个文件会存储很多消息，如何找到某个消息，在文件中具体位置
    // 使用了两个偏移量来进行表示。  [offsetBeg,offsetEnd)
    // 这两个属性不需要序列化保存到文件中，此时消息一旦写入文件，所在的位置就是固定的，并不需要单独保存
    // 这两个属性存在的目的，就是让内存中的 Message 对象，能够快速找到硬盘中的 Message 位置
    private transient long offsetBeg = 0; // 消息数据的开头距离文件开头的位置偏移（字节）
    private transient long offsetEnd = 0; // 消息数据的结尾距离文件开头的位置偏移（字节）
    // 使用这个属性表示该消息在文件中是否有效，（针对文件中的消息，使用逻辑删除方式）
    // 0x1 表示有效; 0x2 表示失效
    private byte isValid = 0x1;

    // 创建一个工厂方法，让工厂方法帮我们封装一下创建 Message 对象的过程
    // 这个方法创建的 Message 对象，会自动生成唯一 MessageId
    public static Message createMessageWithId(String routingKey, BasicProperties basicProperties, byte[] body) {
        Message message = new Message();
        if (basicProperties != null) {
            message.setBasicProperties(basicProperties);
        }
        // 此处生成的 MessageId 用 M- 作前缀区分
        message.setMessageId("M-" + UUID.randomUUID());
        message.setRoutingKey(routingKey);
        message.body = body;

        // 其他参数, offsetBeg offsetEnd isValid 在消息持久化的时候才会用到，在把消息写入文件之前进行设定
        return message;
    }

    public String getMessageId() {
        return basicProperties.getMessageId();
    }

    public void setMessageId(String messageId) {
        basicProperties.setMessageId(messageId);
    }

    public String getRoutingKey() {
        return basicProperties.getRoutingKey();
    }

    public void setRoutingKey(String routingKey) {
        basicProperties.setRoutingKey(routingKey);
    }

    public int getDeliverMode() {
        return basicProperties.getDeliverMode();
    }

    public void setDeliverMode(int mode) {
        basicProperties.setDeliverMode(mode);
    }
}
